﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.IO;


namespace IiiToolkitMain.Common
{
    public class HkSDK
    {

        #region 结构定义
        //数据回调设置
        public enum CallBackDateType
        {
            /// <summary>
            /// 流头
            /// </summary>
            NET_DVR_SYSHEAD = 0,
            /// <summary>
            /// 流数据
            /// </summary>
            NET_DVR_STREAMDATA = 1,
            /// <summary>
            /// 结束标记
            /// </summary>
            NET_DVR_RECV_END = 2,
        }
        public enum MessageType
        {

            /// INS_PLAY_EXCEPTION -> 0
            INS_PLAY_EXCEPTION = 0,

            /// INS_PLAY_RECONNECT -> 1
            INS_PLAY_RECONNECT = 1,

            /// INS_PLAY_RECONNECT_EXCEPTION -> 2
            INS_PLAY_RECONNECT_EXCEPTION = 2,

            /// INS_PLAY_START -> 3
            INS_PLAY_START = 3,

            /// INS_PLAY_STOP -> 4
            INS_PLAY_STOP = 4,

            /// INS_PLAY_ARCHIVE_END -> 5
            INS_PLAY_ARCHIVE_END = 5,

            /// INS_VOICETALK_START -> 16
            INS_VOICETALK_START = 16,

            /// INS_VOICETALK_STOP -> 17
            INS_VOICETALK_STOP = 17,

            /// INS_VOICETALK_EXCEPTION -> 18
            INS_VOICETALK_EXCEPTION = 18,

            /// INS_PTZ_EXCEPTION -> 19
            INS_PTZ_EXCEPTION = 19,

            /// INS_RECORD_FILE -> 20
            INS_RECORD_FILE = 20,

            /// INS_RECORD_SEARCH_END -> 21
            INS_RECORD_SEARCH_END = 21,

            /// INS_RECORD_SEARCH_FAILED -> 22
            INS_RECORD_SEARCH_FAILED = 22,

            /// INS_DEFENSE_SUCCESS -> 23
            INS_DEFENSE_SUCCESS = 23,

            /// INS_DEFENSE_FAILED -> 24
            INS_DEFENSE_FAILED = 24,

            /// INS_PLAY_ARCHIVE_EXCEPTION -> 28
            INS_PLAY_ARCHIVE_EXCEPTION = 28,

            /// INS_PTZCTRL_SUCCESS -> 46
            INS_PTZCTRL_SUCCESS = 46,

            /// INS_PTZCTRL_FAILED -> 47
            INS_PTZCTRL_FAILED = 47,
        }
        
        public enum LoginParamKey
        {
            /// <summary>
            /// 区域号, 目前只有海外使用
            /// </summary>
            LOGIN_AREAID = 1,
            
            /// <summary>
            /// 登录页面版本信息
            /// </summary>
            LOGIN_VER = 2
        }
        public struct StreamTime
        {
            public uint iYear { get; set; }
            public uint iMonth { get; set; }
            public uint iDay { get; set; }
            public uint iHour { get; set; }
            public uint iMinute { get; set; }
            public uint iSecond { get; set; }
        }
        public enum PTZAction
        {
            START,
            STOP
        }
        public enum PTZCommand
        {
            UP,
            DOWN,
            LEFT,
            RIGHT,
            UPLEFT,
            DOWNLEFT,
            UPRIGHT,
            DOWNRIGHT,
            ZOOMIN,
            ZOOMOUT,
            FOCUSNEAR,
            FOCUSFAR,
            IRISSTARTUP,
            IRISSTOPDOWN,
            LIGHT,
            WIPER,
            AUTO
        }
        #endregion

        #region 类型定义
        /// <summary>
        /// 信息回调
        /// </summary>
        /// <param name="sessionId">	申请的会话ID</param>
        /// <param name="msgType">消息号 MessageType</param>
        /// <param name="errorCode">错误码 OpenNetStreamError.h</param>
        /// <param name="info">信息</param>
        /// <param name="pUser">用户自定义数据</param>
        /// <returns></returns>
        public delegate int MessageHandler(IntPtr sessionId, MessageType msgType, uint errorCode, string info, IntPtr pUser);


        /// <summary>
        /// 数据回调格式
        /// </summary>
        /// <param name="dateType">数据类型，参见 DataType</param>
        /// <param name="dateContent">数据内容</param>
        /// <param name="dataLen">数据长度</param>
        /// <param name="pUser">用户自定义数据</param>
        public delegate void DataCallBack(CallBackDateType dateType, IntPtr dateContent, int dataLen, string pUser);

        /// <summary>
        /// 报警消息推送回调函数
        /// </summary>
        /// <param name="szDesc">推送描述信息</param>
        /// <param name="szContent">推送内容</param>
        /// <param name="szDetail">完整的推送信息</param>
        /// <param name="pUser">用户自定义数据</param>
        public delegate void PushMessageHandler(string szDesc, string szContent, string szDetail, IntPtr pUser);

        #endregion
        
        #region 开放SDK初始化

        /// <summary>
        /// 初始化库, 支持配置平台地址
        /// 该接口必须在调用其他接口之前调用
        /// </summary>
        /// <param name="authAddr">认证域名:开放平台认证中心地址，默认地址为：https://auth.ys7.com .对于开发者而言，请填写此默认地址即可.</param>
        /// <param name="platform">平台域名:开放平台后台地址，默认地址为：https://open.ys7.com .对于开发者而言，请填写此默认地址即可.</param>
        /// <param name="appId">向平台申请的AppKey</param>
        /// <returns>0表示成功，-1表示失败</returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_InitLib(string authAddr, string platform, string appId);

        /// <summary>
        /// //初始化库, 默认国内版本使用的接口
        /// </summary>
        /// <param name="szAppId">向平台申请的AppKey</param>
        /// <returns>0表示成功，-1表示失败</returns>
        [DllImport("sdkOpenNetStream.dll")]
        public static extern int OpenSDK_Init(string szAppId);

        /// <summary>
        /// 反初始化库
        /// </summary>
        /// <returns>0表示成功，-1表示失败</returns>
        [DllImport("sdkOpenNetStream.dll")]
        public static extern int OpenSDK_FiniLib();

        /// <summary>
        /// 设置AccessToken
        /// </summary>
        /// <param name="szAccessToken">token值</param>
        /// <returns>0表示成功，-1表示失败</returns>
        [DllImport("sdkOpenNetStream.dll")]
        public static extern int OpenSDK_SetAccessToken(string szAccessToken);

        #endregion

        #region 分配会话

        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_AllocSession(MessageHandler callback, IntPtr userId, ref IntPtr sessionId, ref int sesstionLength, bool bSync, uint timeout);

        //[DllImport("OpenNetStream.dll")]
        //public static extern int OpenSDK_AllocSessionEx(MessageHandler callback, IntPtr userId, ref IntPtr sessionId, ref int sesstionLength);
        /// <summary>
        /// 销毁SDK操作句柄
        /// </summary>
        /// <param name="sessionId">会话Id，通过OpenSDK_AllocSession()创建</param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_FreeSession(string sessionId);

        #endregion
        
        #region 预览接口

        /// <summary>
        /// 设置数据回调 
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="pDataCallBack"></param>
        /// <param name="pUser"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]//设置数据回调窗口
        public static extern int OpenSDK_SetDataCallBack(IntPtr sessionId, DataCallBack pDataCallBack, string pUser);
        /// <summary>
        /// 设置或者切换清晰度
        /// </summary>
        /// <param name="szDevSerial">设备序列号</param>
        /// <param name="iChannelNo">设备通道号 </param>
        /// <param name="iVideoLevel">视频质量，输入范围在0-2之间 </param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_SetVideoLevel(string szDevSerial, int iChannelNo, int iVideoLevel);

        /// <summary>
        /// 开始播放，异步接口，返回值只是表示操作成功，不代表播放成功 播放结果根据消息回调函数msgid判断, 若msgid=INS_PLAY_START, 表示播放成功, 若msgid=INS_PLAY_EXCEPTION, 表示播放失败
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="playWnd"></param>
        /// <param name="cameraId"></param>
        /// <param name="token"></param>
        /// <param name="videoLevel"></param>
        /// <param name="safeKey"></param>
        /// <param name="appKey"></param>
        /// <param name="pNscbMsg"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]//SDK开始播放
        public static extern int OpenSDK_StartRealPlay(IntPtr sid, IntPtr playWnd, string cameraId, string token, int videoLevel, string safeKey, string appKey, uint pNscbMsg);

        /// <summary>
        /// 停止播放播放，返回值只是表示操作成功，不代表播放成功, 结果根据消息回调函数msgid判断
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="pNscbMsg"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]//SDK关闭播放
        public static extern int OpenSDK_StopRealPlay(IntPtr sid, uint pNscbMsg);

        #endregion

        #region 回放接口

        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_PlayBackPause(IntPtr sid);

        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_PlayBackResume(IntPtr sid);

        /// <summary>
        /// 开始回放, 异步接口，返回值只是表示操作成功，不代表播放成功 播放结果根据消息回调函数msgid判断, 若msgid=INS_PLAY_START, 表示播放成功, 若msgid=INS_PLAY_EXCEPTION, 表示播放失败 
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="playWnd"></param>
        /// <param name="deviceSerial"></param>
        /// <param name="channelNo"></param>
        /// <param name="safeKey">视频加密密钥 </param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_StartPlayBack(IntPtr sid,IntPtr playWnd,string deviceSerial,int channelNo,string safeKey,string startTime,string endTime);

        /// <summary>
        /// 录像搜索，包含云存储和设备SD卡录像, 只支持按天搜索, 异步接口，返回值只是表示操作成功，不代表播放成功, 结果根据消息回调函数msgid判断 
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="deviceSerial"></param>
        /// <param name="channelNo"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_StartSearch(IntPtr sid, string deviceSerial, int channelNo,string startTime, string endTime);


        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_StopPlayBackEx(IntPtr sid);

        #endregion

        #region 视频信息获取

        /// <summary>
        /// 截屏，StartRealPlay成功（回调函数中收到MsgId == INS_PLAY_START）情况下使用 
        /// </summary>
        /// <param name="SID"></param>
        /// <param name="szFileName">szFile支持中文，都是需要转为UTF-8格式 </param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]//截屏
        public static extern int OpenSDK_CapturePicture(IntPtr SID, string szFileName);

        /// <summary>
        /// 获取OSD时间
        /// </summary>
        /// <param name="SID"></param>
        /// <param name="pTime"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_GetOSDTime(IntPtr SID,out StreamTime pTime);
        #endregion


        #region 音频相关接口
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_CloseSound(IntPtr sid);

        /// <summary>
        /// 获取音量 
        /// </summary>
        /// <param name="sid"></param>
        /// <returns>小于0表示失败，其他值表示音量大小(0-100之间) </returns>
        [DllImport("OpenNetStream.dll")]
        public static extern short OpenSDK_GetVolume(IntPtr sid);

        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_OpenSound(IntPtr sid);

        /// <summary>
        /// 设置音量 
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="volumeValue">音量大小，0-100之间 </param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_SetVolume(IntPtr sid,short volumeValue);


        #endregion

        #region 语音对讲

        /// <summary>
        /// 启语音对讲, 不支持多个设备同时对接 
        /// </summary>
        /// <param name="sid"></param>
        /// <param name="deviceSerial"></param>
        /// <param name="channelNo"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_StartVoiceTalk(IntPtr sid, string deviceSerial,int channelNo);

        /// <summary>
        /// 结束语音对讲 
        /// </summary>
        /// <param name="sid"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_StopVoiceTalk(IntPtr sid);
        #endregion

        #region 中间页

        /// <summary>
        /// 设置登入传入参数 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_SetLoginParams(LoginParamKey key,string value);


        /// <summary>
        /// 获取AreaDomain, (海外不用区域才使用此接口) 
        /// </summary>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_GetAreaDomain();



        /// <summary>
        /// 登陆接口
        /// </summary>
        /// <param name="pToken"></param>
        /// <param name="tokenLth"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Mid_Login(ref string pToken, ref int tokenLth);



        [DllImport("OpenNetStream.dll")]//SDK第三方登陆
        public static extern int OpenSDK_Mid_Device_Add(ref string pToken);


        [DllImport("OpenNetStream.dll")]//SDK第三方登陆
        public static extern int OpenSDK_Mid_Device_Oper(ref string pToken, string deviceId);
        
        #endregion

        #region 数据接口

        /// <summary>
        /// 获取报警列表 
        /// </summary>
        /// <param name="deviceSerial"></param>
        /// <param name="channelNo"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="alarmType"></param>
        /// <param name="status"></param>
        /// <param name="iPageStart"></param>
        /// <param name="iPageSize"></param>
        /// <param name="pBuf"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_GetAlarmList(string deviceSerial,int channelNo, string startTime,string endTime,uint alarmType,int status, int iPageStart, int iPageSize, out IntPtr pBuf, out int iLength);

        /// <summary>
        /// 设置报警已读 
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="alarmId"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_SetAlarmRead(string accessToken,string alarmId);

        /// <summary>
        /// 获取摄像头列表 
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="iPageStart"></param>
        /// <param name="iPageSize"></param>
        /// <param name="pBuf"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_GetDevList(string accessToken, int iPageStart, int iPageSize, out IntPtr pBuf, out int iLength);

        /// <summary>
        /// 获取单个设备信息 
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="deviceSerial"></param>
        /// <param name="pBuf"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_GetDeviceInfo(string accessToken, string deviceSerial, out IntPtr pBuf, out int iLength);

        /// <summary>
        /// 获取设备详细信息, 包括预览能力级, PTZ, 对讲能力级等. 
        /// </summary>
        /// <param name="deviceSerial"></param>
        /// <param name="channelNo"></param>
        /// <param name="update">是否重新获取设备详细信息, true:重新从萤石平台拿数据, 否则拿缓存信息. true的时机为用户重新登录或者需要刷新设备信息. </param>
        /// <param name="pBuf"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_GetDevDetailInfo(string deviceSerial,int channelNo,bool update, out IntPtr pBuf, out int iLength);

        /// <summary>
        ///  解密告警图片(建议加密的图片才调用，非加密图片直接下载，可以通过url里面isEncrypted=1来区分) 
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="picUrl"></param>
        /// <param name="deviceSerial"></param>
        /// <param name="safeKey"></param>
        /// <param name="pBuf">解密后图片内容（需要调用OpenSDK_Data_Free释放内存） </param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_DecryptPicture(string accessToken, string picUrl, string deviceSerial,string safeKey, out IntPtr pBuf, out int iLength);

        /// <summary>
        /// 销毁SDK分配的内存 
        /// </summary>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_Free(IntPtr pBuf);
        
        /// <summary>
        /// 删除设备
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="deviceSerial"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Data_DeleteDevice(string accessToken,string deviceSerial);
        #endregion

        #region 设备操作相关接口

        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_PTZCtrl(IntPtr sid,string deviceSerial,int channelNo,uint command, uint action,int speed);

        #endregion


        #region 通用工具接口

        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_HttpSendWithWait(string szUri, string szHeaderParam, string szBody, out IntPtr iMessage, out int iLength);

        #endregion

        #region 消息推送

        /// <summary>
        /// 设置告警推送回调 
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="pUser">用户自定义数据，回调函数会原样抛出 </param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Push_SetAlarmCallBack(PushMessageHandler callback, string pUser);

        /// <summary>
        /// 设置设备上下线状态推送  
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="pUser"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Push_SetDeviceStatusCallBack(PushMessageHandler callback, string pUser);

        /// <summary>
        /// 设置设备上下线状态推送  
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="pUser"></param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Push_SetTransparentChannelCallBack(PushMessageHandler callback, string pUser);

        /// <summary>
        /// 开始接收推送 
        /// </summary>
        /// <param name="pushSecret">接入Push所使用密钥，创建应用的时候有平台生成 </param>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Push_StartRecv(string pushSecret);

        /// <summary>
        /// 停止接收告警 
        /// </summary>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_Push_StopRecv();

        #endregion

        #region 错误码信息接口

        /// <summary>
        /// 获取错误码接口 
        /// </summary>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_GetLastErrorCode();

        /// <summary>
        /// 错误码描述 
        /// </summary>
        /// <returns></returns>
        [DllImport("OpenNetStream.dll")]
        public static extern int OpenSDK_GetLastErrorDesc();

        #endregion

    }
}
